---
id: apollo-federation
title: Apollo Federation
---


import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

In many cases, exposing single GraphQL API that exposes unified view of all the available data provides tremendous value
to their clients. As the underlying graph scales, managing single monolithic GraphQL server might become less and less
feasible making it much harder to manage and leading to unnecessary bottlenecks. Migrating towards federated model with
an API gateway and a number of smaller GraphQL services behind it alleviates some of those problems and allows teams to
scale their graphs more easily.

[Apollo Federation](https://www.apollographql.com/docs/federation/) is an architecture for composing multiple GraphQL
services into a single graph. Federated schemas rely on a number of custom directives to instrument the behavior of the
underlying graph and convey the relationships between different schema types. Each individual GraphQL server generates a
valid GraphQL schema and can be run independently. This is in contrast with a traditional schema stitching approach where
relationships between individual services, i.e. linking configuration, is configured at the GraphQL gateway level.

## Federation v1 vs Federation v2

Federation v2 is an evolution of the Federation spec to make it more powerful, flexible and easier to adapt. While v1 and
v2 schemas are similar in many ways, Federation v2 relaxes some of the constraints and adds additional capabilities. See
[Apollo documentation](https://www.apollographql.com/docs/federation/federation-2/new-in-federation-2/) for details.

By default, `graphql-kotlin-federation` library will generate Federation v1 compatible schema. In order to generate v2
compatible schema you have to explicitly opt-in by specifying `optInFederationV2 = true` on your instance of `FederatedSchemaGeneratorHooks`.

```kotlin
val myHooks = FederatedSchemaGeneratorHooks(resolvers = myFederatedResolvers, optInFederationV2 = true)
val myConfig = FederatedSchemaGeneratorConfig(
  supportedPackages = "com.example",
  hooks = myHooks
)

toFederatedSchema(
  config = myConfig,
  queries = listOf(TopLevelObject(MyQuery()))
)
```

:::note
Federation v2 compatible schemas, can be generated using `graphql-kotlin-spring-server` by configuring `graphql.federation.optInV2 = true` property.
:::

## Install

Using a JVM dependency manager, link `graphql-kotlin-federation` to your project.

<Tabs
  defaultValue="gradle"
  values={[
    { label: 'Gradle Kotlin', value: 'gradle' },
    { label: 'Maven', value: 'maven' }
  ]
  }>

  <TabItem value="gradle">

```kotlin
implementation("com.expediagroup", "graphql-kotlin-federation", latestVersion)
```

  </TabItem>
  <TabItem value="maven">

```xml
<dependency>
  <groupId>com.expediagroup</groupId>
  <artifactId>graphql-kotlin-federation</artifactId>
  <version>${latestVersion}</version>
</dependency>
```

  </TabItem>
</Tabs>

## Usage

`graphql-kotlin-federation` is build on top of `graphql-kotlin-schema-generator` and adds a few extra methods and class to use to generate federation compliant schemas.

### `toFederatedSchema`

Just like the basic [toSchema](../schema-generator-getting-started.mdx), `toFederatedSchema` accepts five parameters: `config`, `queries`, `mutations`, `subscriptions` and `schemaObject`.
The difference is that the `config` class is of type [FederatedSchemaGeneratorConfig](https://github.com/ExpediaGroup/graphql-kotlin/blob/master/generator/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/generator/federation/FederatedSchemaGeneratorConfig.kt).
This class extends the [base configuration class](../customizing-schemas/generator-config.md) and adds some default logic. You can override the logic if needed, but do so with caution as you may no longer generate a spec compliant schema.

You can see the definition for `toFederatedSchema` [in the
source](https://github.com/ExpediaGroup/graphql-kotlin/blob/master/generator/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/generator/federation/toFederatedSchema.kt).

### Example

```kotlin
@KeyDirective(fields = FieldSet("id"))
data class User(
  val id: ID,
  val name: String
)

class Query {
  fun getUsers(): List<User> = getUsersFromDB()
}

val config = FederatedSchemaGeneratorConfig(
  supportedPackages = "com.example",
  hooks = FederatedSchemaGeneratorHooks(emptyList(), optInFederationV2 = true)
)

toFederatedSchema(
  config = config,
  queries = listOf(TopLevelObject(Query()))
)
```

will generate

```graphql
schema @link(import : ["@composeDirective", "@extends", "@external", "@inaccessible", "@interfaceObject", "@key", "@override", "@provides", "@requires", "@shareable", "@tag", "FieldSet"], url : "https://specs.apollo.dev/federation/v2.3"){
  query: Query
}

directive @composeDirective(name: String!) repeatable on SCHEMA
directive @extends on OBJECT | INTERFACE
directive @external on FIELD_DEFINITION
directive @inaccessible on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
directive @interfaceObject on OBJECT
directive @key(fields: FieldSet!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE
directive @link(import: [String], url: String!) repeatable on SCHEMA
directive @override(from: String!) on FIELD_DEFINITION
directive @provides(fields: FieldSet!) on FIELD_DEFINITION
directive @requires(fields: FieldSet!) on FIELD_DEFINITION
directive @shareable on OBJECT | FIELD_DEFINITION
directive @tag(name: String!) repeatable on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION

type Query {
   getUsers: [User!]!

   _entities(representations: [_Any!]!): [_Entity]!
   _service: _Service!
}

type User @key(fields : "id", resolvable : true) {
   id: ID!
   name: String!
}

union _Entity = User

type _Service {
   sdl: String!
}

scalar FieldSet
scalar _Any
```

## Limitations

Apollo Federation currently does not support subscriptions. See [Apollo blog](https://www.apollographql.com/blog/backend/federation/using-subscriptions-with-your-federated-data-graph/)
for a workaround.
